// Copyright (C) 2025 Kumo inc.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//

#ifndef ROTHAR_PEGTL_POSITION_HPP
#define ROTHAR_PEGTL_POSITION_HPP

#include <cstdlib>
#include <ostream>
#include <sstream>
#include <string>
#include <utility>

#include "config.hpp"

#include "internal/iterator.hpp"

namespace rothar
{
   struct position
   {
      position() = delete;

#if defined( __GNUC__ ) && !defined( __clang__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
      position( position&& p ) noexcept
         : byte( p.byte ),
           line( p.line ),
           column( p.column ),
           source( std::move( p.source ) )
      {}
#if defined( __GNUC__ ) && !defined( __clang__ )
#pragma GCC diagnostic pop
#endif

      position( const position& ) = default;

      position& operator=( position&& p ) noexcept
      {
         byte = p.byte;
         line = p.line;
         column = p.column;
         source = std::move( p.source );
         return *this;
      }

      position& operator=( const position& ) = default;

      template< typename T >
      position( const internal::iterator& in_iter, T&& in_source )
         : byte( in_iter.byte ),
           line( in_iter.line ),
           column( in_iter.column ),
           source( std::forward< T >( in_source ) )
      {}

      template< typename T >
      position( const std::size_t in_byte, const std::size_t in_line, const std::size_t in_column, T&& in_source )
         : byte( in_byte ),
           line( in_line ),
           column( in_column ),
           source( in_source )
      {}

      ~position() = default;

      std::size_t byte;
      std::size_t line;
      std::size_t column;
      std::string source;
   };

   inline bool operator==( const position& lhs, const position& rhs ) noexcept
   {
      return ( lhs.byte == rhs.byte ) && ( lhs.source == rhs.source );
   }

   inline bool operator!=( const position& lhs, const position& rhs ) noexcept
   {
      return !( lhs == rhs );
   }

   inline std::ostream& operator<<( std::ostream& os, const position& p )
   {
      return os << p.source << ':' << p.line << ':' << p.column;
   }

   [[nodiscard]] inline std::string to_string( const position& p )
   {
      std::ostringstream oss;
      oss << p;
      return std::move( oss ).str();
   }

}  // namespace rothar

#endif
